using System;
using System.IO;
using EasyStorage;
using EventFlowLibrary;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace ScreenManagement
{
    /// <summary>
    /// The pause menu comes up over the top of the game,
    /// giving the player options to resume or quit.
    /// </summary>
    class PauseMenuScreen : MenuScreen
    {
        #region Fields

        World world;

        #endregion

        #region Initialization


        /// <summary>
        /// Constructor.
        /// </summary>
        public PauseMenuScreen(World _world)
            : base("Paused")
        {
            world = _world;

            // Add the Resume Game menu entry.
            MenuEntry resumeGameMenuEntry = new MenuEntry("Resume Game");
            resumeGameMenuEntry.Selected += OnCancel;
            MenuEntries.Add(resumeGameMenuEntry);

            // Add save game entry
            MenuEntry SaveGameMenuEntry = new MenuEntry("Save Game");
            SaveGameMenuEntry.Selected += SaveGameMenuEntry_Selected;
            MenuEntries.Add(SaveGameMenuEntry);

            // If this is a single player game, add the Quit menu entry.
            MenuEntry quitGameMenuEntry = new MenuEntry("Quit Game");
            quitGameMenuEntry.Selected += QuitGameMenuEntrySelected;
            MenuEntries.Add(quitGameMenuEntry);
        }

        public override void LoadContent()
        {
            base.LoadContent();

            this.ScreenManager.SaveDevice.SaveCompleted -= SaveDevice_SaveCompleted;
            this.ScreenManager.SaveDevice.SaveCompleted += new SaveCompletedEventHandler(SaveDevice_SaveCompleted);
        }

        #endregion

        #region Handle Input


        /// <summary>
        /// Event handler for when the Quit Game menu entry is selected.
        /// </summary>
        void QuitGameMenuEntrySelected(object sender, PlayerIndexEventArgs e)
        {
            MessageBoxScreen confirmQuitMessageBox = new MessageBoxScreen(new string[] { "Are you sure you want to quit this game?" }, true, true, true, true);

            confirmQuitMessageBox.Accepted += ConfirmQuitMessageBoxAccepted;

            ScreenManager.AddScreen(confirmQuitMessageBox, ControllingPlayer);
        }

        void SaveGameMenuEntry_Selected(object sende, PlayerIndexEventArgs e)
        {
            // make sure the device is ready
            if (this.ScreenManager.SaveDevice.IsReady)
            {
                // Show box
                MessageBoxScreen currentSaveMessageBox = new MessageBoxScreen(new string[] { "Saving, please wait..." }, false, false, false, false);
                currentSaveMessageBox.Cancelled -= OnCancel;
                currentSaveMessageBox.Accepted -= OnCancel;
                ScreenManager.AddScreen(currentSaveMessageBox, this.ControllingPlayer.Value);

                // Save file
                string fileName = "Save" + DateTime.Now.Ticks;

                RenderTarget2D renderTarget = new RenderTarget2D(this.ScreenManager.GraphicsDevice, 480, 270, false, SurfaceFormat.Color, DepthFormat.Depth16);
                this.ScreenManager.GraphicsDevice.SetRenderTarget(renderTarget);
                world.Draw(new GameTime());
                this.ScreenManager.GraphicsDevice.SetRenderTarget(null);

                // save a file asynchronously. this will trigger IsBusy to return true
                // for the duration of the save process.
                this.ScreenManager.SaveDevice.SaveAsync(
                    "FromTheSeaPt1",
                    fileName + "_save",
                    stream =>
                    {
                        uint[] colorData = new uint[renderTarget.Width * renderTarget.Height];
                        renderTarget.GetData<uint>(colorData);

                        using (BinaryWriter writer = new BinaryWriter(stream))
                        {
                            // Write the screenshot
                            writer.Write(colorData.Length);
                            for (int i = 0; i < colorData.Length; i++)
                            {
                                writer.Write(colorData[i]);
                            }
                            writer.Write(world.XmlLevel);                           // Write which XML file we are using
                            writer.Write((double)world.CharacterPosition.X);        // Write the character position
                            writer.Write((double)world.CharacterPosition.Y);
                            writer.Write((double)world.CharacterPosition.Z);
                            writer.Write((double)world.CharacterOrientation.X);     // Write the character orientation
                            writer.Write((double)world.CharacterOrientation.Y);
                            writer.Write((double)world.CharacterOrientation.Z);
                            writer.Write((double)world.CharacterOrientation.W);
                            writer.Write((double)world.CameraPitch);                // Write the camera pitch
                            writer.Write((double)world.CameraYaw);                  // Write the camera yaw
                            writer.Write((double)world.TotalRotationY);             // Write total y rotation for character
                            writer.Write(world.TimePlayed);                         // Write the time played in milliseconds
                            writer.Write(DateTime.Now.ToBinary());                  // Write the save time
                        }
                    });
            }
            else
            {
                MessageBoxScreen warningMessageBox = new MessageBoxScreen(new string[] { "Save device is not ready. Please retry." }, true, false, true, true);
                warningMessageBox.Accepted += OnCancel;
                ScreenManager.AddScreen(warningMessageBox, this.ControllingPlayer.Value);
            }
        }

        /// <summary>
        /// Event handler for when the user selects ok on the "are you sure
        /// you want to quit" message box. This uses the loading screen to
        /// transition from the game back to the main menu screen.
        /// </summary>
        void ConfirmQuitMessageBoxAccepted(object sender, PlayerIndexEventArgs e)
        {
            //LoadingScreen.Load(ScreenManager, false, null, new BackgroundScreen(),
            //                                               new MainMenuScreen());
            LoadingScreen.Load(ScreenManager, false, null, new BackgroundScreen(), new StartScreen());
        }

        void SaveDevice_SaveCompleted(object sender, FileActionCompletedEventArgs args)
        {
            this.ScreenManager.SaveDevice.SaveCompleted -= SaveDevice_SaveCompleted;

            // Remove topmost screen
            ScreenManager.RemoveScreenTopmost();

            if (args.Error == null)
            {
                // Saved successfully
                MessageBoxScreen warningMessageBox = new MessageBoxScreen(new string[] { "File saved!" }, true, false, true, true);
                warningMessageBox.Cancelled += OnCancel;
                warningMessageBox.Accepted += OnCancel;
                ScreenManager.AddScreen(warningMessageBox, this.ControllingPlayer.Value);
            }
            else
            {
                // Errored
                MessageBoxScreen warningMessageBox = new MessageBoxScreen(new string[] { "Error saving file. ", args.Error.Message }, true, false, true, true);
                warningMessageBox.Cancelled += OnCancel;
                warningMessageBox.Accepted += OnCancel;
                ScreenManager.AddScreen(warningMessageBox, this.ControllingPlayer.Value);
            }
        }

        #endregion
    }
}
